package iws.g5.uebung3;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import iws.g5.uebung3.enums.OrganicType;
import iws.g5.uebung3.interfaces.LivingOrganicObject;
import iws.g5.uebung3.interfaces.OrganicObject;

/**
 * Class holding the environment information
 * @author t.ganzert
 *
 */
public class StateModel {
	static final int DIMENSION_X=300;
	static final int DIMENSION_Y=300;
	
	HashMap<LivingOrganicObject, Integer>cellXPositions =new HashMap<LivingOrganicObject, Integer>();
	HashMap<LivingOrganicObject, Integer>cellYPositions =new HashMap<LivingOrganicObject, Integer>();
	
	private OrganicObject[][] elements=new OrganicObject[DIMENSION_Y][DIMENSION_X];
	private EventCalendar timeController;
	
	public StateModel(EventCalendar t){
		this.timeController=t;
	}
	
	/**
	 * Method for testing, if an position is empty
	 * @param x x position
	 * @param y y position
	 * @return true if position is empty
	 */
	public boolean isPositionEmpty(int x, int y){
		return(elements[y][x]==null)?true:false;
	}
	
	/**
	 * Method for adding an OrganicObject to the environment
	 * @param object OrganicObject to be added
	 * @param x x position
	 * @param y y position
	 */
	public void addOrganicObject(OrganicObject object, int x, int y){
			elements[y][x]=object;
			if(object.getType()==OrganicType.CELL || object.getType()==OrganicType.VIRUS){
				cellXPositions.put((LivingOrganicObject)object,new Integer(x));
				cellYPositions.put((LivingOrganicObject)object,new Integer(y));
				((LivingOrganicObject)object).setPosition(x,y);
				timeController.subscribe((LivingOrganicObject)object);
			}
	}
	
	/**
	 * Method for removing an OrganicObject at a specified position
	 * @param x x position
	 * @param y y position
	 */
	public void removeOrganicObject(int x, int y){
		OrganicObject object=elements[y][x];
		if(object != null && (object.getType()==OrganicType.CELL || object.getType()==OrganicType.VIRUS)){
			cellXPositions.remove(object);
			cellYPositions.remove(object);
			timeController.unsubscribe((LivingOrganicObject)object);
		}
		elements[y][x]=null;
	}
	
	/**
	 * Method for getting an OrganicObject at a specified position
	 * @param x x position
	 * @param y y position
	 * @return OrganicObject at the specified position
	 */
	public OrganicObject getOrganicObject(int x, int y){
		return elements[y][x];
	}
	
	/**
	 * Method for getting the OrganicType of the OrganicObject at a specified position
	 * @param x x position
	 * @param y y position
	 * @return OrganicType of the OrganicObject at the specified position
	 */
	public OrganicType getTypeOfElement(int x, int y){
		if(isPositionEmpty(x,y)){
			return null;
		}else if(elements[y][x].getType()==OrganicType.CELL){
			return OrganicType.CELL;
		}else if(elements[y][x].getType()==OrganicType.VIRUS){
			return OrganicType.VIRUS;
		}else
			return OrganicType.FOOD;
	}
	
	/**
	 * Method for getting the x position of an OrganicObject
	 * @param organicObject
	 * @return x position
	 */
	public int getXPositionForOrganicObject(OrganicObject organicObject){
		if(cellXPositions.containsKey(organicObject)) {
			return cellXPositions.get(organicObject);			
		} else {
			return -1;
		}
	}
	
	/**
	 * Method for getting the y position of an OrganicObject
	 * @param organicObject
	 * @return y position
	 */
	public int getYPositionForOrganicObject(OrganicObject organicObject){
		if(cellYPositions.containsKey(organicObject)) {
			return cellYPositions.get(organicObject);			
		} else {
			return -1;
		}
	}
    
	/**
	 * Get x dimension of environment
	 * @return x dimension of environment
	 */
	public int getXDimension(){
		return DIMENSION_X;
	}
	
	/**
	 * Get y dimension of environment
	 * @return y dimension of environment
	 */
	public int getYDimension(){
		return DIMENSION_Y;
	}
}
